package org.pi.common.geom

/**
 * @author pierre
 * A Point class for float-valued points.
 */
class Point(val x: Float, val y: Float) {
	
	/** compute homogeneous coordinates.
	* @return a 3d vector representing this point as homogeneous coordinates.
	*/
	def homogeneousCoordinates = Vector3f(x,y,1)
  
	/** Compute the distance to another point
	* @param p the other point
	* @return the euclidean distance from this point to the other point.
	*/
	def distance(p: Point) = Math.sqrt( ((x-p.x)*(x-p.x)+(y-p.y)*(y-p.y)).doubleValue ).floatValue()
	
	/** Compute the dot product of two points.
	 * @param p another point.
	 * @return the dotproduct of this point and the other point.
	 */
	def dotprod(p: Point) = x*p.x+y*p.y
	
	/** Compute the eclidean length.
	 * @return the eclidean length of the vector representing this point.
	 */
	def length() = Math.sqrt( (x*x+y*y).doubleValue() ).floatValue()
	
	/** divides this point by a scala factor.
	 * @param value the divisor.
	 * @return a point representing this point divided by a scalar factor.
	 */
	def /(value: Float) = Point(x/value, y/value)

	/** multiplies this point by a scala factor.
	 * @param value the multiplicator.
	 * @return a point representing this point multiplied by a scalar factor.
	 */
	def *(value: Float) = Point(x*value, y*value)

	/** adds a constant to this point.
	 * @param value the value to be added.
	 * @return a point representing this point with a value added to it's elements.
	 */
	def +(value: Float) = Point(x+value, y+value)

	/** subtracts a constant from this point.
	 * @param value the value to be subtracted.
	 * @return a point representing this point with a value subtracted to it's elements.
	 */
	def -(value: Float) = Point(x-value, y-value)
	
	/** Element-wise division.
	 * @param p point to be element-wise divided.
	 * @return a point representing this point element-wise divided by another point.
	 */
	def /(p: Point) = Point(x/p.x, y/p.y)

	/** Element-wise multipplication.
	 * @param p point to be element-wise multiplied.
	 * @return a point representing this point element-wise multiplied by another point.
	 */
	def *(p: Point) = Point(x*p.x, y*p.y)
	
	/** Element-wise addition.
	 * @param p point to be element-wise added.
	 * @return a point representing this point element-wise added to another point.
	 */
	def +(p: Point) = Point(x+p.x, y+p.y)

	/** Element-wise subtraction.
	 * @param p point to be element-wise subtracted.
	 * @return a point representing the other point element-wise subtracted form this point.
	 */
	def -(p: Point) = Point(x-p.x, y-p.y)

	/** Normalizes this point.
	 * @return a point representing a vector of length 1 pointing in the same direction as this point.
	 */
	def normalize() = this / length()
	
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	override def toString() = "("+x+","+y+")"
}

/**
 * @author pierre
 * Singleton access for Points.
 */
object Point {
	/** Creates a new Point.
	 * @param x the x coordinate
	 * @param y the y coordinate
	 * @return the new Point
	 */
	def apply(x: Float, y: Float) = new Point(x,y)
	/** Creates a Point from a Point given in homogeneous coordinates as 3D Vector.
	 * @param v the point in homogeneous coordinates.
	 * @return the new Point
	 */
	def apply(v: Vector3f) = new Point(v(0)/v(2), v(1)/v(2))
}
